﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using InkFx.WinControl.Theme;
using InkFx.WinControl.Utils;
using DA = InkFx.WinControl.XIDEAlignment;
using DTGS = InkFx.WinControl.XIDEGroupState;

namespace InkFx.WinControl
{
    /// <summary>
    /// 
    /// </summary>
    [ToolboxItem(false)]
    public partial class XIDETipForm : System.Windows.Forms.Form
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="idePanel">Type: XIDEPanel</param>
        /// <param name="tag">Type: System.Object</param>
        /// <param name="floatForm">Type: XIDEFloatForm</param>
        public XIDETipForm(XIDEPanel idePanel, object tag, XIDEFloatForm floatForm)
        {
            InitializeComponent();
            //base.DoubleBuffered = true; //这种需要快速弹出的窗体, 设置 双缓冲 只会减慢启动速度
            base.ShowInTaskbar = false;
            //base.BackColor = Color.BlueViolet;


            this.TipTag = tag;
            this.IDEPanel = idePanel;
            this.Group = floatForm.Group;

            this.FloatForm = floatForm;
            this.FloatForm.FormClosed += FloatFormClosed;
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="idePanel">Type: XIDEPanel</param>
        /// <param name="tag">Type: System.Object</param>
        /// <param name="floatForm">Type: XIDEFloatForm</param>
        /// <returns></returns>
        public static XIDETipForm ShowTipForm(XIDEPanel idePanel, object tag, XIDEFloatForm floatForm)
        {
            var group = floatForm == null ? null : floatForm.Group;
            if (group == null) return null;

            var ctrl = tag as System.Windows.Forms.Control;
            Rectangle rect = Rectangle.Empty;
            if (ctrl != null) { rect = Win32API.GetWindowRectangle(ctrl.Handle); }
            else if (tag == XIDEFloatForm.CENTER_TIPTAG) { rect = idePanel.FindCenterRectWindow(); }

            var parent = idePanel.FindForm();
            XIDETipForm form = new XIDETipForm(idePanel, tag, floatForm);
            form.TopMost = true;
            form.Bounds = rect;
            form.Show(parent);
            //form.Owner = parent;
            //Win32API.ShowWindow(form.Handle, 4);

            return form;
        }


        /// <summary>
        /// 内部字段
        /// </summary>
        protected XIDELayoutInfo m_TipLayout = null;
        /// <summary>
        /// 内部字段
        /// </summary>
        protected List<XIDEAreaInfo> m_ListTipArea = new List<XIDEAreaInfo>();


        /// <summary>
        /// 
        /// </summary>
        public void ResetRect()
        {
            var tag = TipTag;
            var ctrl = tag as System.Windows.Forms.Control;

            #region  计算 附着区域

            m_ListTipArea.Clear();
            if (ctrl != null)
            {
                var rect = Win32API.GetWindowRectangle(ctrl.Handle);
                this.Bounds = rect;

                if (ctrl is XIDEPanel)
                {
                    #region  IDEPanel 四周的附着区域

                    var ctrl1 = (XIDEPanel)ctrl;
                    const int OFFSET = 3;
                    const int SIZE = 28;
                    int width = this.Width;
                    int height = this.Height;
                    Rectangle rectT = new Rectangle((width - SIZE) / 2, OFFSET, SIZE, SIZE);
                    Rectangle rectB = new Rectangle((width - SIZE) / 2, height - SIZE - OFFSET, SIZE, SIZE);
                    Rectangle rectL = new Rectangle(OFFSET, (height - SIZE) / 2, SIZE, SIZE);
                    Rectangle rectR = new Rectangle(width - SIZE - OFFSET, (height - SIZE) / 2, SIZE, SIZE);


                    var areaT = new XIDEAreaInfo(DA.Top, ctrl1) { Rect = rectT };
                    var areaB = new XIDEAreaInfo(DA.Bottom, ctrl1) { Rect = rectB };
                    var areaL = new XIDEAreaInfo(DA.Left, ctrl1) { Rect = rectL };
                    var areaR = new XIDEAreaInfo(DA.Right, ctrl1) { Rect = rectR };
                    m_ListTipArea.AddRange(new[] { areaT, areaB, areaL, areaR });

                    #endregion
                }
                else if (ctrl is XIDEGroup)
                {
                    #region  Group 的拆分附着区域

                    var ctrl3 = (XIDEGroup)ctrl;
                    bool hide = (ctrl3 == this.Group) || (ctrl3.State != DTGS.Expand && ctrl3.State != DTGS.Float && ctrl3.State != DTGS.Popup);

                    if (hide) { m_TipLayout = null; }
                    else
                    {
                        m_TipLayout = new XIDELayoutInfo(XIDELayoutMode.Group, (XIDEGroup)ctrl);
                        m_TipLayout.Rect = new Rectangle(Point.Empty, this.Size);
                        //Console.WriteLine(m_TipLayout.TipRect);
                    }

                    #endregion
                }
            }
            else if (tag == XIDEFloatForm.CENTER_TIPTAG)
            {
                #region  主文档 中央的附着区域

                var idePanel = this.IDEPanel;
                var rect = idePanel.FindCenterRect();
                var rectW = idePanel.FindCenterRectWindow();
                this.Bounds = rectW;

                const int SIZE = 28;
                int width = rect.Width;
                int height = rect.Height;
                Rectangle rectC = new Rectangle((width - SIZE) / 2, (height - SIZE) / 2, SIZE, SIZE);

                var areaC = new XIDEAreaInfo(DA.Center, this.IDEPanel) { Rect = rectC };
                m_ListTipArea.Add(areaC);

                #endregion
            }
            #endregion

            #region  计算Region

            var oldRegion = this.Region;
            var newRegion = new Region(Rectangle.Empty);

            if (m_TipLayout != null && m_TipLayout.Group != null)
            {
                newRegion.Union(m_TipLayout.TipRect.RectCenter);
                newRegion.Union(m_TipLayout.TipRect.RectLeft);
                newRegion.Union(m_TipLayout.TipRect.RectRight);
                newRegion.Union(m_TipLayout.TipRect.RectTop);
                newRegion.Union(m_TipLayout.TipRect.RectBottom);
            }
            else if (m_ListTipArea != null && m_ListTipArea.Count >= 1)
            {
                foreach (var area in m_ListTipArea)
                    newRegion.Union(area.Rect);
            }

            //this.Region = new Region(new Rectangle(0, 0, 100, 100));
            this.Region = newRegion;
            if (oldRegion != null) oldRegion.Dispose();


            #endregion

        }


        /// <summary>
        /// 
        /// </summary>
        public XIDEFloatForm FloatForm { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public XIDEPanel IDEPanel { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public XIDEGroup Group { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public object TipTag { get; private set; }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: EventArgs</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            ResetRect();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: EventArgs</param>
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            base.DoubleBuffered = true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: EventArgs</param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            IDEPanel = null;
            TipTag = null;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: EventArgs</param>
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            this.Invalidate2();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: PaintEventArgs</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                base.OnPaint(e);

                var g = e.Graphics;
                var idePanel = this.IDEPanel;
                var theme = idePanel == null ? null : idePanel.Theme;
                if (theme == null) return;

                var tag = this.TipTag;
                var ctrl = tag as System.Windows.Forms.Control;
                if (tag != XIDEFloatForm.CENTER_TIPTAG && (ctrl == null || !ctrl.IsHandleCreated || ctrl.Disposing || ctrl.IsDisposed)) return;


                //不再将所有提示区域 显示在同一个窗体上

                if (m_TipLayout != null && m_TipLayout.Group != null)
                    OnPaintGroupAreas(e, g, theme, m_TipLayout);

                if (m_ListTipArea != null && m_ListTipArea.Count >= 1)
                    foreach (var area in m_ListTipArea)
                    {
                        var align = area.Align;
                        if (align != DA.Top && align != DA.Bottom && align != DA.Left && align != DA.Right && align != DA.Center) continue;
                        OnPaintPanelAreas(e, g, theme, area);
                    }
            }
            catch (Exception ex) { Tools.LogWarn2(ex, "改写 XIDETipForm.OnPaint(PaintEventArgs e) 发生错误"); }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: PaintEventArgs</param>
        /// <param name="g">Type: Graphics</param>
        /// <param name="theme">Type: ThemeXIDEPanel</param>
        /// <param name="area">Type: XIDEAreaInfo</param>
        public virtual void OnPaintPanelAreas(PaintEventArgs e, Graphics g, ThemeXIDEPanel theme, XIDEAreaInfo area)
        {
            const bool debug = false;

            if (debug)
            {
                #region  DEBUG 重绘模式

                Color colorT = Color.FromArgb(200, Color.IndianRed);
                Color colorB = Color.FromArgb(200, Color.IndianRed);
                Color colorL = Color.FromArgb(200, Color.CornflowerBlue);
                Color colorR = Color.FromArgb(200, Color.CornflowerBlue);
                Color colorC = Color.FromArgb(200, Color.DarkCyan);

                var align = area.MouseInTipRect();
                if (align == DA.Top) colorT = Color.FromArgb(255, colorT);
                if (align == DA.Bottom) colorB = Color.FromArgb(255, colorB);
                if (align == DA.Left) colorL = Color.FromArgb(255, colorL);
                if (align == DA.Right) colorR = Color.FromArgb(255, colorR);
                if (align == DA.Center) colorR = Color.FromArgb(255, colorR);

                if (area.Align == DA.Top) g.FillRectangle(new SolidBrush(colorT), area.Rect);
                if (area.Align == DA.Bottom) g.FillRectangle(new SolidBrush(colorB), area.Rect);
                if (area.Align == DA.Left) g.FillRectangle(new SolidBrush(colorL), area.Rect);
                if (area.Align == DA.Right) g.FillRectangle(new SolidBrush(colorR), area.Rect);
                if (area.Align == DA.Center) g.FillRectangle(new SolidBrush(colorC), area.Rect);

                #endregion
            }
            else
            {
                #region  正式重绘

                var hover = area.MouseInRect();
                OnPaintAreaTip(e, g, theme, area.Rect, area.Align, hover);

                #endregion
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: PaintEventArgs</param>
        /// <param name="g">Type: Graphics</param>
        /// <param name="theme">Type: ThemeXIDEPanel</param>
        /// <param name="layout">Type: XIDELayoutInfo</param>
        public virtual void OnPaintGroupAreas(PaintEventArgs e, Graphics g, ThemeXIDEPanel theme, XIDELayoutInfo layout)
        {
            const bool debug = false;
            
            if (debug)
            {
                #region  DEBUG 重绘模式

                Color colorC = Color.FromArgb(200, Color.Coral);
                Color colorT = Color.FromArgb(200, Color.IndianRed);
                Color colorB = Color.FromArgb(200, Color.IndianRed);
                Color colorL = Color.FromArgb(200, Color.CornflowerBlue);
                Color colorR = Color.FromArgb(200, Color.CornflowerBlue);

                var align = layout.MouseInTipRect();
                if (align == DA.Center) colorC = Color.FromArgb(255, colorC);
                if (align == DA.Top) colorT = Color.FromArgb(255, colorT);
                if (align == DA.Bottom) colorB = Color.FromArgb(255, colorB);
                if (align == DA.Left) colorL = Color.FromArgb(255, colorL);
                if (align == DA.Right) colorR = Color.FromArgb(255, colorR);

                g.FillRectangle(new SolidBrush(colorC), layout.TipRect.RectCenter);


                g.FillRectangle(new SolidBrush(colorT), layout.TipRect.RectTop);
                g.FillRectangle(new SolidBrush(colorB), layout.TipRect.RectBottom);
                g.FillRectangle(new SolidBrush(colorL), layout.TipRect.RectLeft);
                g.FillRectangle(new SolidBrush(colorR), layout.TipRect.RectRight);

                #endregion
            }
            else
            {
                #region  正式重绘

                var align = layout.MouseInTipRect();
                OnPaintAreaTip(e, g, theme, layout.TipRect.RectCenter, DA.Center, align == DA.Center);
                OnPaintAreaTip(e, g, theme, layout.TipRect.RectTop, DA.Top, align == DA.Top);
                OnPaintAreaTip(e, g, theme, layout.TipRect.RectBottom, DA.Bottom, align == DA.Bottom);
                OnPaintAreaTip(e, g, theme, layout.TipRect.RectLeft, DA.Left, align == DA.Left);
                OnPaintAreaTip(e, g, theme, layout.TipRect.RectRight, DA.Right, align == DA.Right);

                #endregion
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="e">Type: PaintEventArgs</param>
        /// <param name="g">Type: Graphics</param>
        /// <param name="theme">Type: ThemeXIDEPanel</param>
        /// <param name="rect">Type: Rectangle</param>
        /// <param name="align">Type: XIDEAlignment</param>
        /// <param name="hover">Type: bool</param>
        public virtual void OnPaintAreaTip(PaintEventArgs e, Graphics g, ThemeXIDEPanel theme, Rectangle rect, XIDEAlignment align, bool hover)
        {
            if (theme == null || align == DA.None) return;

            var imgV10 = theme.XIDETipForm_Area_V10;

            int index = 0;
            if (align == DA.Center) index = 0;
            else if (align == DA.Top) index = 1;
            else if (align == DA.Bottom) index = 2;
            else if (align == DA.Left) index = 3;
            else if (align == DA.Right) index = 4;
            int index2 = index * 2 + (hover ? 1 : 0);
            imgV10.DrawImage(g, index2, rect);
        }


        private bool m_InvalidateTipRect = false;
        /// <summary>
        /// 
        /// </summary>
        public new void Invalidate2()
        {
            if (m_TipLayout != null && m_TipLayout.MouseInRect())
            {
                var align = m_TipLayout.MouseInTipRect();
                if (align != DA.None) { base.Invalidate(m_TipLayout.TipRect.RectFull); m_InvalidateTipRect = true; return; }
            }

            if (m_ListTipArea != null && m_ListTipArea.Count >= 1)
            {
                foreach (var area in m_ListTipArea) { if (area.MouseInRect()) { base.Invalidate(area.Rect); m_InvalidateTipRect = true; return; } } 
            }

            if (m_InvalidateTipRect) { base.Invalidate(); m_InvalidateTipRect = false; }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public XIDETipEventArgs NewTipEventArgs()
        {
            var layout = m_TipLayout;
            var dockAreas = m_ListTipArea;

            if (layout != null)
            {
                var align = layout.MouseInTipRect();
                if (align != DA.None)
                {
                    //MessageBox.Show("tabGroup");
                    return new XIDETipEventArgs { Group = layout.Group, TipLayout = layout, Alignment = align };
                }
            }

            if (dockAreas != null)
                foreach (var area in dockAreas)
                {
                    var align = area.MouseInTipRect();
                    if (align != DA.None)
                    {
                        //MessageBox.Show("tabGroup");
                        return new XIDETipEventArgs { Group = null, TipArea = area, Alignment = area.Align };
                    }
                }

            return null;
        }

        /// <summary>
        /// 当浮动窗体关闭时, 将所有的提示窗体也关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void FloatFormClosed(object sender, FormClosedEventArgs e)
        {
            if (FloatForm != null) FloatForm.FormClosed -= FloatFormClosed;
            FloatForm = null;
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual new void Dispose()
        {
            TipTag = null;
            Group = null;
            IDEPanel = null;

            if (!this.Disposing && !this.IsDisposed) { this.Close(); base.Dispose(); }
        }
    }
}
